const PENDDING = 'pendding';
const FULLFILLED = 'fullfilled';
const REJECTED  = 'rejected';

let uiid = 0;
class MyPromise{
    _value = undefined;         //用于存储resolve接口参数
    _error = undefined;         //用于存储reject接口参数
    status = PENDDING;          //用于记录当前promise对象的状态

    successCbStacks = [];  //存储promise状态为FULLFILLED的所有调用函数
    failCbStacks = [];     //存储promise状态为REJECTED时所有的调用函数

    constructor(executor){
        try{
            executor(this.resolve, this.reject);
        } catch(e){
            this.reject(e);
        }
    }
    resolve = (value) => {  //这一步比较巧妙。就是在变更promise的状态为FULLFILLED的时候，同时将之前注册的尚未执行的成功回调一个一个进行执行。
        if (PENDDING !== this.status) {
            return;
        }
        this._value = value;
        this.status = FULLFILLED;
        queueTask(this.successCbStacks);
    }
    reject = (error) => {  //这一步比较巧妙。就是在变更promise的状态为REJECTED的时候，同时将之前注册的待执行的失败回调一个一个进行执行。
        if (PENDDING !== this.status) {
            return;
        }
        this._error = error;
        this.status = REJECTED;
        queueTask(this.failCbStacks);
    }
    //理解一下，promise的then是可以进行链式调用的。我需要关心下一个then的输入参数是个啥？
    then(successCallBack, failCallBack){
        let responsePromise = new MyPromise((resolve, reject)=>{
            queueMicrotask(()=>{
                this.handlerThenCallBack(successCallBack,failCallBack,responsePromise);
            })
        });
        return responsePromise;
    }
    handlerThenCallBack(successCallBack,failCallBack,thenResponsePromise){
        successCallBack = 'function' == typeof successCallBack ? successCallBack : (value => {return value});
        failCallBack =  'function' == typeof failCallBack ? failCallBack : (error => {throw error});
        this.successCbStacks.push(()=>{    
            try{
                let response = successCallBack(this._value);
                this.handlerResponseCall(response,thenResponsePromise);
            }catch(err){
                thenResponsePromise.reject(err);
            }
        });
        this.failCbStacks.push(()=>{
            try {
                let response = failCallBack(this._error);
                this.handlerResponseCall(response,thenResponsePromise);
            } catch (err) {
                thenResponsePromise.reject(err);
            }
            
        });
        if (FULLFILLED == this.status) {
            queueTask(this.successCbStacks);
        }else if (REJECTED == this.status) {
            queueTask(this.failCbStacks);
        }
    }
    handlerResponseCall(response , responsePromise){
        queueMicrotask(()=>{    //then返回的promise的注册函数放到下一个微任务队列中执行。就是为了链式调用的then的微任务队列会在更深的一层
            if (response instanceof MyPromise) {
                if (response === responsePromise) { //如果then的注册的回调函数返回的值为promise对象。且和这个then函数本身的返回的promise是同一个对象。则报错
                    responsePromise.reject(TypeError('Chaining cycle detected for promise #<Promise>]'));
                }else{
                    //当一个then的注册函数返回值是promise对象的时候。这个promise对象状态决定了then函数返回的promise对象的状态和它的注册函数的参数。
                    response.then(responsePromise.resolve,responsePromise.reject);  //这一步就是注册了 这个promise的 成功回调和失败回调。
                }
            }else{
                responsePromise.resolve(response); 
            }
        })
    }
    catch(failCallBack){    //用于捕获错误
       return this.then(undefined,failCallBack)
    }
    static resolve(value){   //用于生成一个是fullfilled状态的promise
        return new MyPromise((resolve,reject)=>{
            resolve(value);
        });
    }
    static reject(err){
        return new MyPromise((resolve, reject)=>{
            return reject(err);
        })
    }
    static all(promises){   //同时执行多个promise。等到所有的都变成fullfilled或者有一个变为reject。则all返回的proimse变为fullfilled或者变为reject
        return allHellp(promises,false);
    }
    static allSettled(promises){
        return allHellp(promises,true);
    }
    static race(promises){
        let beResolved = false;
        let promise = new MyPromise((resolve,reject)=>{
            for (let index = 0; index < promises.length; index++) {
                const p = promises[index];
                if (p instanceof MyPromise) {
                    p.then((value)=>{
                        if (beResolved) {
                            return;
                        }else{
                            beResolved = true; //若有一个fullfilled结束，就立即resolve该状态。
                            resolve(value);
                        }
                    },(err)=>{
                        if (beResolved) {
                            return;
                        }else{
                            beResolved = true;// 若有一个reject，也立即reject该状态
                            reject(err);
                        }
                    })
                }else{
                    //如果碰到非promise对象。直接置位fullfilled
                    beResolved = true
                    resolve(p); 
                    break;
                }
            }
        })
        return promise;
    }

}

function allHellp(promises,isSettled){      //isSettled用于判断是否是Settled状态的调用
    let totalParamLength = promises.length; //获取所以参数的总长度，用于决定返回的promise何时进行resolve操作。
    let result = new Array();                  //创建数组用于存储promises所有的异步执行结果。
    let totalResolved = 0;                     //临时变量用于统计已经有多少个promise状态变为fullfilled。 当它等于totalParamLength的时候 all创建的promise就可以进行rosolve操作。
    let promise = new MyPromise((resolve, reject) => {
        for (let index = 0; index < promises.length; index++) {
            const current = promises[index];
            if (current instanceof MyPromise) {
                current.then((value)=>{     //将所有的Promise对象注册回调函数，并在回调函数中判断是不是所有的状态都变为fullfilled或其中一个变为rejected。或者所有的状态都变为不是pendding
                    if (isSettled) {    //如果是settled模式。则将状态和值一起缓存
                        addResult({status:FULLFILLED,value:value},index);
                    }else{
                        addResult(value,index);
                    }
                },err=>{
                    if (isSettled) {
                        addResult({status:REJECTED,reason:err},index);//如果是settled模式。则将状态和值一起缓存
                    } else {
                        reject(err);
                    }
                })
            } else {
                if (isSettled) {
                    addResult({status:FULLFILLED,value:current},index); //如果是settled模式。则将状态和值一起缓存
                }else{
                    addResult(current,index)
                }
            }
        }
    })
    function addResult(response,index){
        totalResolved++;
        result[index] = response;
        if (totalResolved == totalParamLength) {
            promise.resolve(result);
        }
    }
    return promise;
}

/**
 * 
 *辅助函数 用于启动promise对象的then函数所注册的回调函数
 */
function queueTask(tasks) {       
    while(tasks.length){
        try {
            tasks.shift()();
        } catch (error) {
            throw (error);
        }
    }
}
module.exports = MyPromise;